/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.smsspamreport;

import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;

/**
 * This filter is called upon the reception of a SMS.<br/>
 * <p>
 * It will retrieve the message from the SMS and check if it contain a premium-number phone number.<br/>
 * If it does , it will add a notification to the user about the suspicious message.
 * </p>
 * <p>
 * If the message is coming from the 33700 and is requesting more information , it will send a SMS to the 33700 with the phone number from the last reported message.<br/>
 * If it is a notification that the message has been successfully reported, it will notified the user of the success of the operation.
 * </p>
 * @author Christophe Petit
 *
 */
/**
 * @author coincoin
 *
 */
/**
 * @author coincoin
 *
 */
public class SMSFilter extends BroadcastReceiver {
	//Suite au bug http://code.google.com/p/android/issues/detail?id=16669
	//Pour tester , se connecter en telnet et lancer les commandes sms pdu
	//PDUs pour tester : message de 33700 blahcompléterblah :
	//				002005813307f0000011501102909380116276183d7eb7e1ec02bd2c17b3c368
	//                message de 33700 blahterminée.blah
	//				002005813307f00000115011020260800f6276184d2fcbdb6977A12C6687D1



	private Context mContext;

	public static final String SPAMNUMBER="SPAMNUMBER";
	public static final String SPAMTEXT="SPAMTEXT";
	@Override
	public void onReceive(Context context, Intent intent) {
		mContext=context;
		Bundle bundle = intent.getExtras();        
		String message = "";        
		if (bundle != null)
		{
			//---retrieve the SMS message received---
			Object[] pdus = (Object[]) bundle.get("pdus");
			SmsMessage[] messages=new SmsMessage[pdus.length];
			for(int i=0;i<pdus.length;i++) {
				messages[i]=SmsMessage.createFromPdu((byte[]) pdus[i]);

			}
			//Log.d("SMSFILTER", "received "+pdus.length+" messages");
			message = getMessageFromSMSs( messages);
			//Log.d("SMSFilter","message received:"+message);
			if (messages.length>0) {
				String adress=messages[0].getOriginatingAddress();
				if (adress!= null && "33700".equals(adress)){
					persistSMS(message, adress,"inbox");
					handleResponseFrom33700(message);
					abortBroadcast();
				}
			}

			if (isMessageSuspect(message)){
				NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
				Notification notification =new Notification(android.R.drawable.stat_notify_error,"SMS Suspect",System.currentTimeMillis());

				CharSequence contentTitle = "SMS Suspect";
				CharSequence contentText = "Voulez vous signaler ce SMS au 33700 ?";
				Intent notificationIntent = new Intent(context,DisplayArlertActivity.class);
				Log.d("SMSFILTER","message suspect");
				Log.d("SMSFILTER","sender="+messages[0].getOriginatingAddress());
				Log.d("SMSFILTER","body="+message);				
				notificationIntent.putExtra(DisplayArlertActivity.SMS_BODY, message);
				notificationIntent.putExtra(DisplayArlertActivity.SMS_SENDER, messages[0].getOriginatingAddress());
				notification.flags |= Notification.FLAG_AUTO_CANCEL;
				PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

				notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
				mNotificationManager.notify(1, notification);
				//on sauvegarde quand même le sms dans la boite de reception
				persistSMS(message, messages[0].getOriginatingAddress(),"inbox");
				abortBroadcast();
			}
		}
	}

	/**
	 * Save a SMS to the default Android SMS application.
	 * 
	 * @param message
	 * The text of the SMS.
	 * @param sender
	 * The phone number of the SMS.
	 * @param box
	 * The box where to store the message.
	 */
	private void persistSMS( String message, String sender, String box) {
		ContentValues values = new ContentValues();
		values.put("address", sender);
		values.put("body", message);
		mContext.getContentResolver().insert(Uri.parse("content://sms/"+box), values);
	}

	/**
	 * 
	 * construct the full text of the sms if the SMS was too long to fit on a single message<br/>
	 * 
	 * @param sms
	 * An array of SMSs.
	 * @return
	 * The complete text of the SMS.
	 */
	private String getMessageFromSMSs(SmsMessage[] sms) {
		String str="";
		for(SmsMessage message:sms) {
			str += message.getMessageBody().toString();
		}
		return str;
	}

	private void handleResponseFrom33700(String message) {
		if (message.contains("terminée")) {
			Log.d("SMSFilter", "Confirmation du 33700 recue");
			clearSpammerNumber();
		} else if(message.contains("compléter")) {
			Log.d("SMSFilter", "demande du 33700 pour l'éméteur du spam");
			sendSpammerNumber();
		}

	}

	/**
	 * Send the phone number of the last reported message by SMS to the 33700.
	 */
	private void sendSpammerNumber() {
		String number=mContext.getSharedPreferences("spamNumber", Context.MODE_PRIVATE).getString(SPAMNUMBER,"");
		number=FrenchPhoneNumberHelper.check(number);
		if (number != null) {
			SmsManager.getDefault().sendTextMessage("33700", null, number, null, null);
			persistSMS(number, "33700","sent");
		}

	}
	/**
	 * Send a notification when the SMS has been fully reported to the 33700.
	 */
	private void clearSpammerNumber() {
		mContext.getSharedPreferences("spamNumber", Context.MODE_PRIVATE).edit().remove(SPAMNUMBER).commit();
		NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
		Notification notification =new Notification(R.drawable.emo_im_happy,"Signalement terminé",System.currentTimeMillis());
		CharSequence contentTitle = "Signalement terminé";
		CharSequence contentText = "le 33700 se charge du reste...";
		notification.setLatestEventInfo(mContext, contentTitle, contentText,  PendingIntent.getBroadcast(mContext, 0, new Intent(), 0));
		mNotificationManager.notify(1, notification);

	}
	/**
	 * Check if a SMS contain a premium-rate French phone number.
	 * @param message
	 * The complete SMS message
	 * @return
	 * True if the message contain a premium-rate phone number.<br/>
	 * False otherwise.
	 */
	private boolean isMessageSuspect(String message) {
		List<String> numbers=FrenchPhoneNumberHelper.extractsNumbers(message);
		for(String number:numbers) {
			String numero=FrenchPhoneNumberHelper.check(number);
			if (numero != null && FrenchPhoneNumberHelper.isSuspect(numero)) {
				return true;
			}
		}
		return false;
	}

}
